Overloading on std::function<…?

This is supposed to happen std::function has a constructor template that can take an argument of any type. The compiler can't know until after a constructor template is selected and instantiated that it's going to run into errors, and it has to be able to select an overload of your function before it can do that The most straightforward fix is to use a cast or to explicitly construct a std::function object of the correct type: func(std::function((){})); func(std::function((int){})) If you have a compiler that supports the captureless-lambda-to-function-pointer conversion and your lambda doesn't capture anything, you can use raw function pointers: void func(void (*param)()) { } void func(void (*param)(int)) { } (It looks like you are using Visual C++ 2010, which does not support this conversion. The conversion was not added to the specification until just before Visual Studio 2010 shipped, too late to add it in.

) To explain the problem in a bit more detail, consider the following: template struct function { template function(U f) { } } This is basically what the std::function constructor in question looks like: You can call it with any argument, even if the argument doesn't make sense and would cause an error somewhere else. For example function f(42) would invoke this constructor template with U = int In your specific example, the compiler finds two candidate functions during overload resolution: void func(std::function) void func(std::function) The argument type, some unutterable lambda type name that we will refer to as F doesn't match either of these exactly, so the compiler starts looking at what conversions it can do to F to try and make it match one of these candidate functions. When looking for conversions, it finds the aforementioned constructor template All the compiler sees at this point is that it can call either function because it can convert F to std::functionIt can't pick one because both conversions are equally good and neither overload is better than the other.

This is supposed to happen. Std::function has a constructor template that can take an argument of any type. The compiler can't know until after a constructor template is selected and instantiated that it's going to run into errors, and it has to be able to select an overload of your function before it can do that.

The most straightforward fix is to use a cast or to explicitly construct a std::function object of the correct type: func(std::function((){})); func(std::function((int){})); If you have a compiler that supports the captureless-lambda-to-function-pointer conversion and your lambda doesn't capture anything, you can use raw function pointers: void func(void (*param)()) { } void func(void (*param)(int)) { } (It looks like you are using Visual C++ 2010, which does not support this conversion. The conversion was not added to the specification until just before Visual Studio 2010 shipped, too late to add it in.) To explain the problem in a bit more detail, consider the following: template struct function { template function(U f) { } }; This is basically what the std::function constructor in question looks like: You can call it with any argument, even if the argument doesn't make sense and would cause an error somewhere else. For example, function f(42); would invoke this constructor template with U = int.

In your specific example, the compiler finds two candidate functions during overload resolution: void func(std::function) void func(std::function) The argument type, some unutterable lambda type name that we will refer to as F, doesn't match either of these exactly, so the compiler starts looking at what conversions it can do to F to try and make it match one of these candidate functions. When looking for conversions, it finds the aforementioned constructor template. All the compiler sees at this point is that it can call either function because it can convert F to std::function using its converting constructor with U = F and it can convert F to std::function using its converting constructor with U = F.

In your example it is obvious that only one of these will succeed without error, but in the general case that isn't true. The compiler can't do anything further. It has to report the ambiguity and fail.

It can't pick one because both conversions are equally good and neither overload is better than the other.

Tell me if I got this right. This snippet has the same problem for the same reason (cannot instantiate Struct in time to determine func overload)? Template struct Struct { Struct(T var) {} }; void func2(Struct obj){} void func2(Struct obj){} int main() { func2(2.5); } – Arnavion Jan 19 at 6:06 No, it's a bit different than that.

That error is because T is in a nondeduced context. I'll edit an explanation into my answer; this comment isn't quite large enough. – James McNellis Jan 19 at 6:07 Got it.

Thanks! – Arnavion Jan 19 at 6:28 In many areas of the C++ standard draft, the committee required some constructor/function templates to be excluded from the overload resolution if some conditions are not met. This can usually be achieved by "SFINAE".(See for example shared_ptr's templated constructor).

I wonder why they didn't do something similar here with std::function. – sellibitze Jan 19 at 21:00 @sellibitze: I think that could prove to be difficult given that there are so many different kinds of types that can be stored by a std::function. Even so, in the OP's case, there could still be an ambiguity, e.g. If you passed an object of type struct S { void operator()() { } void operator()(int) { } };.

– James McNellis Jan 19 at 19:14.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions